use crate::prequire::adb::shell::OutputShellCmd;
use crate::prequire::adb::{start_app, switch_keyborad, switch_to_adb_keyborad, tap, text};
use crate::prequire::BinaryCommand;
use crate::project::CatchOptions;
use crate::project::ParseOptions;
use crate::project::{AppPageTapSection, CaptureScenes, Project};
use clap::Subcommand;
use std::path::PathBuf;
use std::thread;
use std::time::Duration;

#[derive(Debug, Subcommand)]
pub enum ProjectActionCommands {
  Search {
    #[arg(short, long, default_value_t = 1, default_missing_value = "1")]
    num: u64,

    #[arg(short, long)]
    train: bool,

    #[arg(short, long, default_value_t = false)]
    preprocess: bool,

    #[arg(short = 'P', long)]
    page_name: String,
    keyword: String,
  },
  Parse {
    #[arg(short, long)]
    train: bool,

    #[arg(short, long, default_value_t = false)]
    preprocess: bool,

    #[arg(short, long)]
    out_dir: Option<String>,

    input_dir: String,
  },
  Test,
  // Search {
  //   #[arg(short, long, default_value_t = 1, default_missing_value = "1")]
  //   num: usize,

  //   #[arg(short, long)]
  //   train: bool,

  //   #[arg(short, long, default_value_t = false)]
  //   preprocess: bool,

  //   #[arg(short = 'P', long)]
  //   page_name: String,
  //   keyword: String,
  // },
}

pub fn serve_commands(proj: &Project, command: &ProjectActionCommands) {
  match command {
    ProjectActionCommands::Search {
      num,
      train,
      preprocess,
      page_name,
      keyword,
    } => {
      if let Some(page) = proj.proj_conf.app.get_page(page_name) {
        if let Some(AppPageTapSection { point, .. }) = page.get_tap("into_search") {
          println!(
            "project action search {} on page <{}> at point<{:?}>",
            keyword, page_name, point
          );
          start_app(&proj.proj_conf.app.name).expect("failed start app");
          // 切换到AdbKeyboard
          switch_to_adb_keyborad().expect("failed switch_to_adb_keyborad");

          thread::sleep(Duration::from_millis(5000));
          println!("switch_to_adb_keyborad done!");

          tap(point.get_x(), point.get_y()).expect("failed tap app");

          thread::sleep(Duration::from_millis(1000));
          println!("tap...{}, {}", point.get_x(), point.get_y());

          // tap(point.get_x(), point.get_y()).expect("failed tap app");
          // thread::sleep(Duration::from_millis(500));

          text(&keyword).expect("failed text app");

          // thread::sleep(Duration::from_millis(500));
          // 发送enter keycode无效
          // keycode(66).expect("failed keycode app");
          // thread::sleep(Duration::from_millis(1000));

          // 切回到设备之前的keyboard
          if proj.device_conf.is_some() {
            let raw_keyboard = proj.device_conf.as_ref().unwrap().keyboard.as_str();
            switch_keyborad(raw_keyboard).expect("failed switch_keyborad");
          }
        } else {
          eprintln!("无法在page<{}>找到tap<into_earch>", page_name);
          return;
        }

        if let Some(AppPageTapSection { point, .. }) =
          page.taps.iter().find(|t| t.to == "do_search")
        {
          tap(point.get_x(), point.get_y()).expect("failed tap app");
        } else {
          eprintln!("无法在page<{}>找到tap<do_search>", page_name);
          return;
        }
      } else {
        eprintln!("无法找到page<{}>", page_name);
        return;
      }
      // 等待查询结果
      thread::sleep(Duration::from_millis(3000));
      if let Some(_page) = proj.proj_conf.app.get_page("search") {
        let out_dir = proj.calc_capture_dir(&keyword, *train);
        if let Err(err) = CatchOptions::new()
          // .set_out_dir(out_dir)
          // .set_num(*num)
          .set_train(*train)
          .set_preprocess(*preprocess)
          .set_scene(CaptureScenes::Keyword)
          .screenshot(&proj.proj_conf, out_dir, *num)
        {
          eprintln!("catch err:{:?}", err);
          return;
        }
      } else {
        eprintln!("无法找到page<search>");
        return;
      }
    }
    ProjectActionCommands::Parse {
      train,
      preprocess,
      out_dir,
      input_dir,
    } => {
      let out_dir = out_dir
        .as_deref()
        .map_or(format!("{}/{}", proj.location.display(), proj.proj_conf.app.parse_dir.to_str().unwrap()), |v| v.to_string());
      if let Err(err) = ParseOptions::new()
        // .set_out_dir(out_dir)
        // .set_num(*num)
        .set_train(*train)
        .set_preprocess(*preprocess)
        .set_scene(CaptureScenes::Keyword)
        .parse(&proj.proj_conf, input_dir, out_dir)
      {
        eprintln!("catch err:{:?}", err);
        return;
      }
    }
    _ => {
      let raw_input_keyboard = OutputShellCmd::new(&["settings get secure default_input_method"])
        .exec()
        .expect("fail to exec outputshell");

      println!("raw_input_keyboard=>{}", raw_input_keyboard);
    }
  }
}
